package com.geezdata.cps.base.utils;

import com.geezdata.cps.base.constant.Constants;
import com.google.common.collect.Lists;

import org.apache.commons.lang3.time.DateUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.temporal.TemporalAdjusters;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

public class DateUtil {

	public static Date parseDateRuntime(String dateString) {
		try {
			return DateUtils.parseDate(dateString, Constants.APPLICATION_DATE_FORMAT);
		} catch (ParseException e) {
			throw new RuntimeException(e);
		}
	}
	
	public static Date parseDateRuntime(String dateString, String... patterns) {
		try {
			return DateUtils.parseDate(dateString, patterns);
		} catch (ParseException e) {
			throw new RuntimeException(e);
		}
	}
	
	public static String format(Date date, String format) {
		if(date == null) return null;
		return new SimpleDateFormat(format).format(date);
	}
	
	public static String formatDate(Date date) {
		return format(date, Constants.APPLICATION_DATE_FORMAT);
	}
	
	public static String formatShortDate(Date date) {
		return format(date, Constants.APPLICATION_DATE_FORMAT_SHORT);
	}
	public static String TimeStamp2Date(String timestampString){
	    Long timestamp = Long.parseLong(timestampString)*1000;
	    String date = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new java.util.Date(timestamp));  
	    return date;
	}
	public static Date getCurrentDate() {
		Date currentDate = new Date();
		String currentStringDate = DateUtil.format(currentDate, Constants.APPLICATION_DATE_FORMAT_SHORT);
		return DateUtil.parseDateRuntime(currentStringDate, Constants.APPLICATION_DATE_FORMAT_SHORT);	
	}
	
	public static Date getYesterdayDate() {
		Date yesterdayDate = getSpecificDate(new Date(), Calendar.DAY_OF_MONTH, -1);
		String yesterdayStringDate = DateUtil.format(yesterdayDate, Constants.APPLICATION_DATE_FORMAT_SHORT);
		return DateUtil.parseDateRuntime(yesterdayStringDate, Constants.APPLICATION_DATE_FORMAT_SHORT);	
	}
	public static Date getTomorrowDate() {
		Date tomorrowDate = getSpecificDate(new Date(), Calendar.DAY_OF_MONTH, 1);
		String tomorrowDateStringDate = DateUtil.format(tomorrowDate, Constants.APPLICATION_DATE_FORMAT_SHORT);
		return DateUtil.parseDateRuntime(tomorrowDateStringDate, Constants.APPLICATION_DATE_FORMAT_SHORT);
	}
	public static Date getDateNextDay(Date date) {
		Calendar calendar = new GregorianCalendar();
		calendar.setTime(date);
		calendar.add(Calendar.DATE,1);
		date=calendar.getTime();
		return date;
	}
	public static Date getSpecificDate(Date date, Integer gapType, Integer gap) {
		Calendar calendar = new GregorianCalendar(); 
		calendar.setTime(date); 
		calendar.add(gapType, gap);
		return calendar.getTime();
	}
	
	public static boolean isSameDay(Date dateA,Date dateB) {
	    Calendar calDateA = Calendar.getInstance();
	    calDateA.setTime(dateA);

	    Calendar calDateB = Calendar.getInstance();
	    calDateB.setTime(dateB);

	    return calDateA.get(Calendar.YEAR) == calDateB.get(Calendar.YEAR)
	            && calDateA.get(Calendar.MONTH) == calDateB.get(Calendar.MONTH)
	            &&  calDateA.get(Calendar.DAY_OF_MONTH) == calDateB.get(Calendar.DAY_OF_MONTH);
	}
	
	public static List<Date> lastNDays(Date currentDate, Integer n) {
		if (n <= 0) {
			return null;
		}
		
		List<Date> lastNDays = Lists.newArrayList();
		for (int i = 1; i <= n; i++) {
			lastNDays.add(DateUtil.getSpecificDate(currentDate, Calendar.DATE, -i));
		 }
		
		return lastNDays;
	}
	
	public static Date getLastSecondOfThisYear() {
		LocalDate today = LocalDate.now();
		LocalDate lastDayOfThisYear = today.with(TemporalAdjusters.lastDayOfYear());
		LocalTime lastSecond = LocalTime.parse("23:59:59");
		LocalDateTime localDateTime = LocalDateTime.of(lastDayOfThisYear, lastSecond);
		ZoneId zone = ZoneId.systemDefault();
	    Instant instant = localDateTime.atZone(zone).toInstant();
	    Date date = Date.from(instant);
		return date;
	}
	
	public static Date getLastSecondOfNextYearToday() {
		LocalDate today = LocalDate.now();
		LocalDate sameDayOfNextYear = today.plusYears(1);
		LocalTime lastSecond = LocalTime.parse("23:59:59");
		LocalDateTime localDateTime = LocalDateTime.of(sameDayOfNextYear, lastSecond);
		ZoneId zone = ZoneId.systemDefault();
	    Instant instant = localDateTime.atZone(zone).toInstant();
	    Date date = Date.from(instant);
		return date;
	}
	
   
   public static Integer getDayGap(Date date1, Date date2) {
	   if(date1 == null || date2 == null) {
		   return null;
	   }
       Calendar calst = Calendar.getInstance();;
       Calendar caled = Calendar.getInstance();

       calst.setTime(date1);
       caled.setTime(date2);

        //设置时间为0时   
        calst.set(Calendar.HOUR_OF_DAY, 0);   
        calst.set(Calendar.MINUTE, 0);   
        calst.set(Calendar.SECOND, 0);   
        caled.set(Calendar.HOUR_OF_DAY, 0);   
        caled.set(Calendar.MINUTE, 0);   
        caled.set(Calendar.SECOND, 0);   
        
       //得到两个日期相差的天数   
        int days = ((int)(caled.getTime().getTime()/1000)-(int)(calst.getTime().getTime()/1000))/3600/24;   
        
       return days;   
   }
   
   public static Date getExpectTime(Date time1, Date time2, boolean earlier) {
	   if (time1 == null || time2 == null) {
		   return time1 != null ? time1 : time2;
	   } 
	
	   if ((earlier && time2.before(time1)) || (!earlier && time1.before(time2))) {
		   return time2;
	   }

	   return time1;
   }
   
   public static Boolean isInTimeWindow(Date time1, Date time2, Integer days) {
		 Integer dayGap = DateUtil.getDayGap(time1, time2);
		 if (dayGap > 0 && dayGap <= days) {
			 return true;
		 } else {
			 return false;
		 }
	 }

	public static Date getFirstSecondOfNextDay() {
		LocalDate today = LocalDate.now();
		LocalDate nextDay = today.plusDays(1);
		LocalTime lastSecond = LocalTime.parse("00:00:01");
		LocalDateTime localDateTime = LocalDateTime.of(nextDay, lastSecond);
		ZoneId zone = ZoneId.systemDefault();
	    Instant instant = localDateTime.atZone(zone).toInstant();
	    Date date = Date.from(instant);
		return date;
	}
	
	public static boolean isSuitableTime(String beginHour, String endHour) {
		SimpleDateFormat df = new SimpleDateFormat("HH:mm");//设置日期格式
		Date now =null;
	    Date beginTime = null;
	    Date endTime = null;
	    try {
	        now = df.parse(df.format(new Date()));
	        beginTime = df.parse(beginHour);
	        endTime = df.parse(endHour);
	    } catch (Exception e) {
	    }

		return belongCalendar(now, beginTime, endTime);
	}
	
	/**
     * 判断时间是否在时间段内
     * @param nowTime
     * @param beginTime
     * @param endTime
     * @return
     */
    public static boolean belongCalendar(Date nowTime, Date beginTime, Date endTime) {
        Calendar date = Calendar.getInstance();
        date.setTime(nowTime);

        Calendar begin = Calendar.getInstance();
        begin.setTime(beginTime);

        Calendar end = Calendar.getInstance();
        end.setTime(endTime);

        return (!date.before(begin) && !date.after(end));
    }


    /**
     * 获取指定时间
     *
     * @param now    当前时间
     * @param field  时间单位
     * @param amount 时间数量
     * @return 目标时间
     */
    public static Date getSpecifiedDate(Date now, int field, int amount) {
        Calendar c = Calendar.getInstance();
        c.setTime(now);
        c.add(field, amount);
        return c.getTime();
    }

    /**
     * 获取某天的开始时间
     */
	public static Date getDateStartTime(Date time) {
		Calendar timeStart = Calendar.getInstance();
		timeStart.setTime(time);
		timeStart.set(Calendar.HOUR_OF_DAY, 0);
		timeStart.set(Calendar.MINUTE, 0);
		timeStart.set(Calendar.SECOND, 0);
		timeStart.set(Calendar.MILLISECOND, 0);
		return timeStart.getTime();
	}

	/**
	 * 获取某天的结束时间
	 */
	public static Date getDateEndTime(Date time) {
		Calendar timeEnd = Calendar.getInstance();
		timeEnd.setTime(time);
		timeEnd.set(Calendar.HOUR_OF_DAY, 23);
		timeEnd.set(Calendar.MINUTE, 59);
		timeEnd.set(Calendar.SECOND, 59);
		timeEnd.set(Calendar.MILLISECOND, 999);
		return timeEnd.getTime();
	}
}
